﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;
using Sukul.SharePoint.Taxomatic.Service;
using System.Xml;
using System.IO;
using Sukul.SharePoint.Common;
using System.Net;

namespace Sukul.SharePoint.Taxomatic
{
    /// <summary>
    /// This class handles the request to download the taxonomy as an XML file and 
    /// also to upload the XML file to re-create the taxonomy
    /// </summary>
    /// <remarks>
    /// Author: Shailen Sukul
    /// Date: 17 Apr 2011
    /// </remarks>
    public class TaxomaticHandler : Sukul.SharePoint.Common.HttpHandler.HttpHandlerBase, IHttpHandler
    {
        public bool IsReusable
        {
            get { return false; }
        }

        private string _SelectedTerms = string.Empty;
        private string _Mode = string.Empty;
        private void ExtractQueryString(HttpContext context)
        {
            _SelectedTerms = string.Empty;
            _Mode = string.Empty;
            if (!String.IsNullOrEmpty(context.Request.QueryString["terms"]))
            {
                _SelectedTerms = context.Request.QueryString["terms"];
            }
            if (!String.IsNullOrEmpty(context.Request.QueryString["mode"]))
            {
                _Mode = context.Request.QueryString["mode"];
            }
        }
        public void ProcessRequest(HttpContext context)
        {
            ExtractQueryString(context);
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.Response.Cache.SetNoStore();
            context.Response.Cache.SetExpires(DateTime.MinValue);

            switch (_Mode.ToLower())
            {
                case "export":
                    Export(context);
                    break;
                case "import":
                    Import(context);
                    break;
                case "convert":
                    Convert(context);
                    break;
                default:
                    About(context);
                    break;
            }
        }

        private void Convert(HttpContext context)
        {
            //System.Diagnostics.Debugger.Break();
            Sukul.SharePoint.Common.DTO.WebServiceResponse response = null;
            string tmpFileName = string.Empty;
            string csvFile = string.Empty;
            string sResponse = string.Empty;
            try
            {
                context.Response.ContentType = Sukul.SharePoint.Common.DTO.ContentType.Application_Json;
                response = new Sukul.SharePoint.Common.DTO.WebServiceResponse();
                if (context.Request.Files.Count == 0)
                {
                    response.IsSuccess = false;
                    response.ErrorMessage = "No upload files were specified.";
                }
                else
                {
                    var strExtension = Path.GetExtension(context.Request.Files[0].FileName).ToLower();

                    if (strExtension != ".xml")
                    {
                        response.IsSuccess = false;
                        response.ErrorMessage = "File extension is not XML";
                    }
                    else
                    {
                        tmpFileName = System.IO.Path.GetTempPath() + System.Guid.NewGuid().ToString() + strExtension;
                        csvFile = System.IO.Path.GetTempPath() + System.Guid.NewGuid().ToString() + ".csv";
                        SaveFileToDisk(context.Request, tmpFileName);

                        new TaxonomyHelper().ConvertTaxonomy(tmpFileName, csvFile);
                        response.IsSuccess = true;
                        //response.Payload = File.ReadAllText(csvFile);

                        context.Response.ContentType = Sukul.SharePoint.Common.DTO.ContentType.Csv;
                        context.Response.Headers.Add("Content-Disposition", "attachment;filename=Taxomatic.csv");

                        // Stream the file back
                        //context.Response.WriteFile(csvFile);
                        base.Cache = context;
                        base.WriteCompressedStream(File.ReadAllText(csvFile), Sukul.SharePoint.Common.DTO.ContentType.Application_CSV);

                        try
                        {
                            if (File.Exists(tmpFileName))
                            {
                                System.IO.File.Delete(tmpFileName);
                            }
                            if (File.Exists(csvFile))
                            {
                                System.IO.File.Delete(csvFile);
                            }
                        }
                        catch { }
                        //context.Response.End();
                        return;
                    }
                }
                sResponse = ServiceBase.Instance.JSONSerializeObject(response, new List<Type> { typeof(DTO.Log) });
            }
            catch (Exception ex)
            {
                sResponse = ServiceBase.Instance.HandleResponseError(response, ex);
            }
            finally
            {
                try
                {
                    if (File.Exists(tmpFileName))
                    {
                        System.IO.File.Delete(tmpFileName);
                    }
                }
                catch { }
            }
            context.Response.StatusCode = (int)HttpStatusCode.OK;
            context.Response.Write(sResponse);
        }

        private void SaveFileToDisk(HttpRequest request, string filePath)
        {
            using (FileStream fileStream = File.Open(filePath, FileMode.Create, FileAccess.Write))
            {
                using (Stream requestStream = request.InputStream)
                {
                    int bufferSize = 1024;
                    byte[] buffer = new byte[bufferSize];
                    int byteCount = 0;

                    //                while ((byteCount = requestStream.Read(buffer, 0, bufferSize)) > 0)
                    while ((byteCount = request.Files[0].InputStream.Read(buffer, 0, bufferSize)) > 0)
                    {
                        fileStream.Write(buffer, 0, byteCount);
                    }
                }
            }
        }

        private void Import(HttpContext context)
        {
            // System.Diagnostics.Debugger.Break();
            Sukul.SharePoint.Common.DTO.WebServiceResponse response = null;
            string tmpFileName = string.Empty;
            string sResponse = string.Empty;
            try
            {
                context.Response.ContentType = Sukul.SharePoint.Common.DTO.ContentType.Application_Json;
                response = new Sukul.SharePoint.Common.DTO.WebServiceResponse();
                if (context.Request.Files.Count == 0)
                {
                    response.IsSuccess = false;
                    response.ErrorMessage = "No upload files were specified.";
                }
                else
                {
                    var strExtension = Path.GetExtension(context.Request.Files[0].FileName).ToLower();

                    if (strExtension != ".xml")
                    {
                        response.IsSuccess = false;
                        response.ErrorMessage = "File extension is not XML";
                    }
                    else
                    {
                        tmpFileName = System.IO.Path.GetTempPath() + System.Guid.NewGuid().ToString() + strExtension;
                        SaveFileToDisk(context.Request, tmpFileName);

                        //                        StreamReader sr = new StreamReader(context.Request.Files[0].InputStream);
                        //                        new TaxonomyHelper().ImportTaxonomy(sr.ReadToEnd());
                        var log = new List<string>();
                        var errorLog = new List<string>();
                        var isOk = new TaxonomyHelper().ImportTaxonomy(tmpFileName, ref log, ref errorLog);
                        response.Payload = new DTO.Log { FullLog = log, ErrorLog = errorLog };
                        response.IsSuccess = isOk;
                    }
                }
                sResponse = ServiceBase.Instance.JSONSerializeObject(response, new List<Type> { typeof(DTO.Log) });
            }
            catch (Exception ex)
            {
                sResponse = ServiceBase.Instance.HandleResponseError(response, ex);
            }
            finally
            {
                try
                {
                    if (File.Exists(tmpFileName))
                    {
                        System.IO.File.Delete(tmpFileName);
                    }
                }
                catch { }
            }
            context.Response.StatusCode = (int)HttpStatusCode.OK;
            context.Response.Write(sResponse);
        }

        private void Export(HttpContext context)
        {
            try
            {
                context.Response.Headers.Add("Content-Disposition", "attachment;filename=Taxomatic.Export.xml");
                context.Response.ContentType = Sukul.SharePoint.Common.DTO.ContentType.Application_Json;
                base.Cache = context;
                base.WriteCompressedStream(TaxonomyHelper.Instance.ExportTaxonomy(), Sukul.SharePoint.Common.DTO.ContentType.Application_XML);
                //context.Response.Write(TaxonomyHelper.Instance.ExportTaxonomy());
            }
            catch
            {
                //Internal Server Error            
                context.Response.StatusCode = 500;
                context.Response.End();
                // context.Response.Write(ex.ToString());
            }
        }

        private void About(HttpContext context)
        {
            context.Response.ContentType = Sukul.SharePoint.Common.DTO.ContentType.Xml;
            context.Response.Write(string.Format(@"<b>Taxomatic</b>{0}<p>This utility allows you to browse, export and import SharePoint taxonomy</p>", @"<br/>"));
        }
        private int HarvestCurrentLCID(System.Web.HttpContext context)
        {
            return (int)Microsoft.SharePoint.WebControls.SPControl.GetContextWeb(context).Language;
        }
    }
}
